package com.ruoyi.controller;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.ruoyi.common.core.utils.StringUtils;
import com.ruoyi.common.security.utils.SecurityUtils;
import com.ruoyi.entity.Driver;
import com.ruoyi.entity.LifeCallbackParam;
import com.ruoyi.service.DriverService;
import com.ruoyi.utils.HttpUtils;
import com.ruoyi.utils.MD5Utils;
import com.ruoyi.utils.R;
import io.minio.MinioClient;
import io.minio.PutObjectArgs;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.http.HttpEntity;
import org.apache.http.NameValuePair;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import org.apache.poi.util.IOUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import sun.misc.BASE64Encoder;

import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletRequest;
import java.awt.*;
import java.awt.font.TextLayout;
import java.awt.geom.AffineTransform;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.time.LocalDate;
import java.time.Period;
import java.time.format.DateTimeFormatter;

/**
 * @author : Xuzhaobo
 * @date : 2024-12-13 14:25
 * @description :
 **/
@RestController
@RequestMapping("/driver")
@CrossOrigin(origins = "*")
public class DriverOcrController {
    // 设置 MinIO 连接信息 这里使用API端口 9000 而不是9001
    String endpoint = "http://47.98.51.135:9000";
    String accessKey = "minio";
    String secretKey = "minio123456";
    String bucketName = "2204";
    String bucketUrl = "http://47.98.51.135:9000/" + bucketName; // MinIO bucket URL
    // 获取当前时间戳
    String flag = System.currentTimeMillis() + " ";
    @Autowired
    DriverService driverService;
    @Autowired
    private StringRedisTemplate redisTemplate;
    private static String appid = "gSPhmyV8uvf4ogQ6";
    private static String secret = "gSPhmyV8uvf4ogQ6i86esvW0YeGRjORP";
    /**
     * @param file:
     * @Description:上传照片到minio加身份证OCR
     * @Author: xuzhaobo
     * @Date: 2024/12/13 15:16
     * @return: java.util.Map
     */
    @PostMapping("/minIOUpload")
    @ResponseBody

        String driverRedis = redisTemplate.opsForValue().get(SecurityUtils.getUserId().toString());
        Map<String, Object> info = null;
        String sign = this.tianYanSign(timeStamp);
        BufferedImage originalImage = ImageIO.read(inputStream);
        BufferedImage watermarkedImage = addWatermark(originalImage, "识别身份证专用");
        ImageIO.write(watermarkedImage, "png", baos);
        byte[] watermarkedData = baos.toByteArray();
        String ocrUrl = "https://api.shumaidata.com/v2/idcard/ocr";
        HttpClient httpClient = HttpClients.createDefault();
        HttpPost httpPost = new HttpPost(ocrUrl);


        HttpResponse response = httpClient.execute(httpPost);

            if (age < 18) {
                return R.ERROR(500, "未到18岁");
            }
            driver.setFrontPhotoCard(image);
            driver.setRealName((String) info.get("name"));
            driver.setIdNumber((String) info.get("number"));
            driver.setGender((String) info.get("sex"));
            String address = (String) info.get("address");
            driver.setNativePlace(address);
            driver.setFamilyAddress(address);



            }
            driver.setReversePhotoCard(image);

        info.put("img", image);
        return R.OK(info);
    }
    /**
     * @param file:
     * @param timeStamp:
     * @param watermarkedInputStream:
     * @param watermarkedData:
     * @param inputStream:
     * @param baos:
     * @Description:上传minio服务器
     * @Author: xuzhaobo
     * @Date: 2024/12/18 15:01
     * @return: java.lang.String
     */
    private String upMinio(MultipartFile file, String timeStamp, ByteArrayInputStream watermarkedInputStream, byte[] watermarkedData, InputStream inputStream, ByteArrayOutputStream baos) throws IOException {
        try {
            String originalFilename = file.getOriginalFilename();
            if (StringUtils.isNull(originalFilename)) {
                throw new IllegalAccessException("文件名不能为空");
            }
            // 生成新的文件名（时间戳+原始文件名） 避免文件名相同被覆盖
            String fileName = timeStamp + "_" + originalFilename;
            // 创建 MinioClient 实例
            MinioClient minioClient = new MinioClient.Builder()
                    .endpoint(endpoint)
                    .credentials(accessKey, secretKey)
                    .build();
            // 构建文件上传相关信息
            PutObjectArgs args = PutObjectArgs.builder()
                    .bucket(bucketName)
                    .object(fileName)
                    .stream(watermarkedInputStream, watermarkedData.length, -1)
                    // application/octet-stream 告诉浏览器这是一个附件，浏览器会直接进行下载，而不是预览
                    .contentType("image/png")
                    .build();
            // 将文件上传到 MinIO 服务器
            minioClient.putObject(args);
            // 生成图片的URL
            String imageUrl = endpoint + "/" + bucketName + "/" + fileName;
            // 返回图片URL给前端
            return imageUrl;
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException("文件上传异常: " + e.getMessage(), e);
        } finally {
            IOUtils.closeQuietly(inputStream);
        }
    }

    @RequestMapping("/upload2")
    public R upload2(MultipartFile file) throws IOException {
        Map<String, Object> info = null;
        String timeStamp = System.currentTimeMillis() + "";
        String sign = this.tianYanSign(timeStamp);
        InputStream inputStream = file.getInputStream();
        BufferedImage originalImage = ImageIO.read(inputStream);
        BufferedImage watermarkedImage = addWatermark(originalImage, "识别驾驶证专用");
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        ImageIO.write(watermarkedImage, "png", baos);
        byte[] watermarkedData = baos.toByteArray();
        ByteArrayInputStream watermarkedInputStream = new ByteArrayInputStream(watermarkedData);
        String imageUrl = upMinio(file, timeStamp, watermarkedInputStream, watermarkedData, inputStream, baos);
        //图片64位
        BASE64Encoder encoder = new BASE64Encoder();
        String base64Str = encoder.encode(watermarkedData);
        //识别驾驶证OCR接口
        String url = "https://api.shumaidata.com/v2/driving_licence/ocr";
        Map<String, String> headers = new HashMap<String, String>();
        headers.put("Content-Type", "application/x-www-form-urlencoded");
        Map<String, Object> params = new HashMap<String, Object>();
        params.put("appid", appid);
        params.put("timestamp", timeStamp);
        params.put("sign", sign);
        params.put("image", base64Str);
        String result = HttpUtils.postForm(url, headers, params);
        Map<String, Object> map = JSONObject.parseObject(result, Map.class);
        if ((Boolean) map.get("success") == true && (Integer) map.get("code") == 200) {
            Map<String, Object> res = (Map<String, Object>) map.get("data");
            info = (Map<String, Object>) res.get("result");
        }
        Map<String, Object> page = null;

        page = (Map<String, Object>) info.get("page_b");
            //判断是否驾驶证副本
            if (StringUtils.isNull(page.get("file_number"))){
                page = (Map<String, Object>) info.get("page_a");
                String dateOfFirstIssue = (String) page.get("date_of_first_issue");
                DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
                LocalDate birthDate = LocalDate.parse(dateOfFirstIssue, formatter);
                // 获取当前日期
                LocalDate currentDate = LocalDate.now();
                // 计算年龄
                Period period = Period.between(birthDate, currentDate);
                int years = period.getYears();
                if (years < 3) {
                    return R.ERROR(500, "驾年龄未到3年");
                }

                driver.setDateFirstApplication(dateOfFirstIssue);
                driver.setValidityPeriodDrivingLicense((String) page.get("valid_date"));
                driver.setQuasiDrivingType((String) page.get("type"));
                driver.setFrontPhotoCard(imageUrl);
                redisTemplate.opsForValue().set(SecurityUtils.getUserId().toString(), JSON.toJSONString(driver));
            }else {
                driver.setReversePhotoCard(imageUrl);
                redisTemplate.opsForValue().set(SecurityUtils.getUserId().toString(), JSON.toJSONString(driver));
            }

        info.put("img", imageUrl);
        return R.OK(info);

    }


    /**
     * @Description:行驶证上传
     * @Author: xuzhaobo
     * @Date: 2024/12/18 19:46
     * @return: com.ruoyi.utils.R
     */
    @PostMapping("/upload3")
    public R upload3(MultipartFile file) throws IOException {
        Map<String, Object> info = null;
        String timeStamp = System.currentTimeMillis() + "";
        String sign = this.tianYanSign(timeStamp);
        InputStream inputStream = file.getInputStream();
        BufferedImage originalImage = ImageIO.read(inputStream);
        BufferedImage watermarkedImage = addWatermark(originalImage, "识别行驶证专用");
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        ImageIO.write(watermarkedImage, "png", baos);
        byte[] watermarkedData = baos.toByteArray();
        ByteArrayInputStream watermarkedInputStream = new ByteArrayInputStream(watermarkedData);
        String imageUrl = upMinio(file, timeStamp, watermarkedInputStream, watermarkedData, inputStream, baos);
        //图片64位
        BASE64Encoder encoder = new BASE64Encoder();
        String base64Str = encoder.encode(watermarkedData);
        Map<String,String> headers = new HashMap<String,String>();
        headers.put("Content-Type","application/x-www-form-urlencoded");
        String url = "https://api.shumaidata.com/v2/vehicle_licence/ocr";
        Map<String,Object> params = new HashMap<String,Object>();
        params.put("appid",appid);
        params.put("timestamp",timeStamp);
        params.put("sign",sign);
        params.put("image", base64Str);
        String result = HttpUtils.postForm(url,headers,params);
        Map<String, Object> map = JSONObject.parseObject(result, Map.class);
        if ((Boolean) map.get("success") == true && (Integer) map.get("code") == 200) {
            Map<String, Object> res = (Map<String, Object>) map.get("data");
            info = (Map<String, Object>) res.get("result");
        }
        if (Objects.isNull(info)){
            return R.ERROR(500,"识别行驶证失败");
        }
        String issueDate = String.valueOf(info.get("issue_date"));
        System.out.println("aaa");


        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        LocalDate birthDate = LocalDate.parse(issueDate, formatter);
        // 获取当前日期
        LocalDate currentDate = LocalDate.now();
        // 计算车的年限
        Period period = Period.between(birthDate, currentDate);
        int years = period.getYears();
        if (years>=8){
            return R.ERROR(500,"车辆年限不符合要求");
        }else {
            info.put("img",imageUrl);
            return R.OK(info);
        }

    }


    /**
     * @param localDate:
     * @Description:检验身份证是否过期
     * @Author: xuzhaobo
     * @Date: 2024/12/18 11:53
     * @return: boolean
     */
    private boolean checkIdCard(LocalDate localDate) {
        LocalDate now = LocalDate.now();
    }

    /**
     * @param request:
     * @param mobile:
     * @Description:活体检测
     * @Author: xuzhaobo
     * @Date: 2024/12/13 19:10
     * @return: java.lang.String
     */
    @GetMapping("/face")
    public String toPage(HttpServletRequest request, String mobile) {
        String callbackUrl = "http://xbo.free.idcfengye.com/driver/result/";
        //由天眼数聚识别页面，识别完成后，需要跳转回我们提供的一个页面。returnUrl就是这个用来接收请求的页面路径
        String returnUrl = "http://127.0.0.1:8080/pages/wait/wait";
        String timestamp = System.currentTimeMillis() + "";
        String sign = this.tianYanSign(timestamp);
        String url = "https://lifeh5.shumaidata.com/index.html#/?appid=" + appid + "&callbackUrl=" + callbackUrl + "&returnUrl=" + returnUrl + "&complexity=2&timestamp=" + timestamp + "&sign=" + sign + "&uid=" + mobile + "&title=八维贷";
        return url;
    }

    private String tianYanSign(String time) {
        return DigestUtils.md5Hex(appid + "&" + time + "&" + secret);
    }
    /**
     * @Description:计算有效期
     * @Author: xuzhaobo
     * @Date: 2024/12/18 19:58
     * @return: java.time.LocalDate
     */

    private static LocalDate checkTimeLimit(String timeLimt) {

        String[] dates = timeLimt.split("-");

        if (dates.length != 2) {
            throw new IllegalArgumentException("无效的有效期格式");
        }

        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMdd");
        LocalDate endDate = LocalDate.parse(dates[1], formatter);

        System.out.println("有效期结束日期: " + endDate);
        return endDate;
    }


    /**
     * @param image:
     * @param watermarkText:
     * @Description:设置图片水印
     * @Author: xuzhaobo
     * @Date: 2024/12/13 18:34
     * @return: java.awt.image.BufferedImage
     */
    private BufferedImage addWatermark(BufferedImage image, String watermarkText) throws IOException {
        int width = image.getWidth();
        int height = image.getHeight();
        // 使用与原始图片相同的类型
        BufferedImage bufferedImage = new BufferedImage(width, height, image.getType());
        Graphics2D g2d = bufferedImage.createGraphics();
        g2d.drawImage(image, 0, 0, null);

        // 设置水印颜色为不透明的红色
        Color semiTransparentRed = new Color(255, 0, 0, 128);
        g2d.setColor(semiTransparentRed);

        // 使用英文字体 Arial
        g2d.setFont(new Font("微软雅黑", Font.BOLD, 56)); // 修改这里

        // 设置透明度
        AlphaComposite alphaComposite = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 1.0f);
        g2d.setComposite(alphaComposite);

        // 计算文本布局
        TextLayout textLayout = new TextLayout(watermarkText, g2d.getFont(), g2d.getFontRenderContext());
        Rectangle2D bounds = textLayout.getBounds();

        // 计算中心位置
        int centerX = (width - (int) bounds.getWidth()) / 2;
        int centerY = (height - (int) bounds.getHeight()) / 2;

        // 设置倾斜角度（例如 20 度）
        AffineTransform transform = new AffineTransform();
        transform.rotate(Math.toRadians(20), centerX + bounds.getWidth() / 2, centerY + bounds.getHeight() / 2);
        g2d.setTransform(transform);

        // 绘制水印
        textLayout.draw(g2d, (float) centerX, (float) centerY + textLayout.getAscent());

        g2d.dispose();
        return bufferedImage;
    }
    /**
     * @Description:根据身份证号计算年龄
     * @Author: xuzhaobo
     * @Date: 2024/12/18 19:58
     * @return: int
     */

    public static int getAgeFromIdCard(String idCard) {
        // 提取出生日期部分
        String birthDateStr = idCard.substring(6, 14);
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMdd");
        LocalDate birthDate = LocalDate.parse(birthDateStr, formatter);
        // 获取当前日期
        LocalDate currentDate = LocalDate.now();
        // 计算年龄
        Period period = Period.between(birthDate, currentDate);
        return period.getYears();
    }


    /**
     * @Description:人证匹配
     * @Author: xuzhaobo
     * @Date: 2024/12/18 19:58
     * @return: void
     */
    @PostMapping("/result")
    @ResponseBody
    public void result(@RequestBody LifeCallbackParam param) throws IOException {
        Map resultInfo = param.getInfo();
        Integer code = (Integer) resultInfo.get("code");
        if (code != 200) {
            return;
        }
        //根据uid（手机号）查询Redis 获取身份证号和姓名
        String mobile = param.getUid();
        Map info = redisTemplate.opsForHash().entries(mobile);
        //根据图片ID拿到图片流,is->base64
        Map data = (Map) resultInfo.get("data");
        String imageId = (String) data.get("feature_image_id");
        String picUrl = "https://api.shumaidata.com/v2/life/check/image?imageId=" + imageId;
        System.out.println(picUrl);
        //如果结果是成功，则需要判断是否认证合一
        //从活体检测的结果中，取出活体检测时候的照片
        String name = (String) info.get("name");
        System.out.println(name);
        String idcard = (String) info.get("number");
        System.out.println(idcard);
        //接口地址
        String url = "https://api.shumaidata.com/v4/face_id_card/compare";
        String timestamp = System.currentTimeMillis() + "";
        String sign = this.tianYanSign(timestamp);
        Map<String, String> headers = new HashMap<String, String>();
        headers.put("Content-Type", "application/x-www-form-urlencoded");
        Map<String, Object> params = new HashMap<String, Object>();
        params.put("appid", appid);
        params.put("timestamp", timestamp);
        params.put("sign", sign);
        params.put("name", name);
        params.put("idcard", idcard);
        params.put("url", picUrl);
        String result = HttpUtils.postForm(url, headers, params);
        Map map = JSONObject.parseObject(result, Map.class);
        Map resultData = (Map) map.get("data");
        //0.45分以上为同一人
        if (resultData.get("msg").equals("系统判断为同一人")) {
            redisTemplate.opsForValue().set("res" + mobile, "true");
        } else {
        }
    }


    /**
     * @param mobile:
     * @param map:
     * @Description:检测手机号是否属于本人
     * @Author: xuzhaobo
     * @Date: 2024/12/16 11:50
     * @return: java.lang.Boolean
     */
    @RequestMapping("/mobileCheck")
    @ResponseBody
    public Boolean mobileCheck(String mobile, @RequestBody Map map) {
        String timestamp = System.currentTimeMillis() + "";
        //参数
        String name = (String) map.get("name");
        String idcard = (String) map.get("number");
        //接口地址
        String url = "https://api.shumaidata.com/v4/mobile_three/transfer";
        String sign = MD5Utils.encrypt(appid + "&" + timestamp + "&" + secret);
        System.out.println("sign: " + sign);

        Map<String, Object> params = new HashMap<String, Object>();
        params.put("appid", appid);
        params.put("timestamp", timestamp);
        params.put("sign", sign);
        params.put("name", name);
        params.put("mobile", mobile);
        params.put("idcard", idcard);

        //请下载 HttpUtils文件，地址为 https://file.tianyandata.cn/demo/utils/HttpUtils.java
        //String result = HttpUtils.get(url, null, params);
        //System.out.println(result);
        //Map resultMap = JSONObject.parseObject(result, Map.class);
        Map resultMap = new HashMap<>();
        resultMap.put("birthday", "20040503");
        resultMap.put("address", "河北邯郸");
        resultMap.put("sex", "男");
        resultMap.put("result", "0");
        Map data = (Map) resultMap.get("data");
        if (resultMap.get("result").equals("0")) {
            //将手机号和身份信息存储起来
            redisTemplate.opsForHash().putAll(mobile, map);
            return true;
        } else {

            return false;
        }
    }

    /**
     * @Description:匹配
     * @Author: xuzhaobo
     * @Date: 2024/12/18 19:57
     * @return: java.lang.Boolean
     */
    @RequestMapping("getFinalResult")
    @ResponseBody
    public Boolean getFinalResult(String mobile) {
        String result = redisTemplate.opsForValue().get("res" + mobile);
        boolean aTrue = result.equals("true");
        return aTrue;
    }


    /**
     * @Description:所有流程执行完将redis里的数据提交到数据库
     * @Author: xuzhaobo
     * @Date: 2024/12/19 15:06
     * @return: com.ruoyi.utils.R
     */
    @GetMapping("/submit")
    public R submit(){
        String driverRedis = redisTemplate.opsForValue().get(SecurityUtils.getUserId().toString());
        Driver driver = JSON.parseObject(driverRedis, Driver.class);
        boolean save = driverService.save(driver);
        if (save){
            return R.OK();
        }else {
            return R.ERROR(500,"失败");
        }


    }

}
